package com.test.textGame.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.test.textGame.dao.ScoreDao;
import com.test.textGame.domain.Player;
import com.test.textGame.domain.PlayerScore;
import com.test.textGame.dto.Score;
import com.test.textGame.exception.GameErrorCode;
import com.test.textGame.exception.GameRuntimeException;
import com.test.textGame.service.ScoreService;
import com.test.textGame.vo.GameCommitVO;
import com.test.textGame.enums.DeletedEnum;
import com.test.textGame.service.Top10Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * Auto created by codeAppend plugin
 */
@Service
public class ScoreServiceImpl extends ServiceImpl<ScoreDao, PlayerScore> implements ScoreService {

    @Autowired
    private Top10Service top10Service;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Score play(GameCommitVO vo) {
        //计算输入文本的分数
        Integer gameScore = manacher(vo.getText());

        //将之前的游戏记录删除
        PlayerScore delete = new PlayerScore();
        delete.setDeleted(DeletedEnum.IS_DELETED.getCode());
        LambdaQueryWrapper<PlayerScore> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PlayerScore::getUserId, vo.getUserId());
        lambdaQueryWrapper.eq(PlayerScore::getDeleted, DeletedEnum.NORMAL.getCode());
        baseMapper.update(delete,lambdaQueryWrapper);

        //保存新的分数
        Date now = new Date();
        PlayerScore insert = new PlayerScore();
        insert.setUserId(vo.getUserId());
        insert.setUserName(vo.getUserName());
        insert.setGameScore(gameScore);
        insert.setCreateTime(now);
        insert.setDeleted(DeletedEnum.NORMAL.getCode());
        baseMapper.insert(insert);

        //更新前10名的排行榜
        try {
            Player player = new Player(vo.getUserId(), vo.getUserName(), now);
            top10Service.updateHeap(player, gameScore);
        } catch (Exception e) {
            throw new GameRuntimeException(GameErrorCode.UPDATE_HEAP_ERROR, e, String.valueOf(vo.getUserId()));
        }

        //返回分数
        Score score = new Score();
        score.setUserId(vo.getUserId());
        score.setUserName(vo.getUserName());
        score.setScore(gameScore);
        return score;
    }

    private int manacher(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        //"12132" -> "#1#2#1#3#2#"
        char[] str = manacherString(s);
        //回文半径的大小
        int[] pArr = new int[str.length];
        int C = -1;
        //R代表最右的扩成功位置的，再下一个位置
        int R = -1;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < str.length; i++) { // 0 1 2
            //R第一个违规的位置，i>= R
            //i位置扩出来的答案，i位置扩的区域，至少是多大
            pArr[i] = R > i ? Math.min(pArr[2 * C - i], R - i) : 1;
            while (i + pArr[i] < str.length && i - pArr[i] > -1) {
                if (str[i + pArr[i]] == str[i - pArr[i]])
                    pArr[i]++;
                else {
                    break;
                }
            }
            if (i + pArr[i] > R) {
                R = i + pArr[i];
                C = i;
            }
            max = Math.max(max, pArr[i]);
        }
        return max - 1;
    }

    private char[] manacherString(String str) {
        char[] charArr = str.toCharArray();
        char[] res = new char[str.length() * 2 + 1];
        int index = 0;
        for (int i = 0; i != res.length; i++) {
            res[i] = (i & 1) == 0 ? '#' : charArr[index++];
        }
        return res;
    }


}